package cc.rengu.igas.bomp.core.service.trans;

import cc.rengu.igas.bomp.common.constant.DubboMethodConstant;
import cc.rengu.igas.bomp.common.enums.RespCodeEnum;
import cc.rengu.igas.bomp.core.service.base.ManageService;
import cc.rengu.igas.bomp.facade.bean.OcrBusinessLicenseInfoBean;
import cc.rengu.igas.bomp.facade.bean.OcrCardInfoBean;
import cc.rengu.igas.bomp.facade.bean.OcrIdInfoBean;
import cc.rengu.igas.bomp.facade.request.OcrRequest;
import cc.rengu.igas.bomp.facade.response.OcrResponse;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.smps.facade.base.Header;
import cc.rengu.igas.smps.facade.request.BankCardRecogRequest;
import cc.rengu.igas.smps.facade.request.BusinessLicenseRecogRequest;
import cc.rengu.igas.smps.facade.request.IdentityCertRecogRequest;
import cc.rengu.igas.smps.facade.response.BankCardRecogResponse;
import cc.rengu.igas.smps.facade.response.BusinessLicenseRecogResponse;
import cc.rengu.igas.smps.facade.response.IdentityCertRecogResponse;
import cc.rengu.igas.smps.facade.result.Result;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.CollectionUtils;

import java.util.Optional;

/**
 * OCR识别
 *
 * @author zhangxr
 * @version 1.0
 * @date 2020.04.21
 */
public class OcrService extends ManageService {

    /**
     * 识别身份证
     */
    public static final String ID_CARD_TYPE = "01";

    /**
     * 识别银行卡
     */
    public static final String BANK_CARD_TYPE = "02";

    /**
     * 识别营业执照
     */
    public static final String LICENSE_TYPE = "03";


    @Override
    protected Object bizBeforeCust() throws Exception {
        OcrRequest ocrRequest = new OcrRequest();
        ConvertUtil.convertOutput(ocrRequest);

        if (StringUtil.isEmptyOrNull(ocrRequest.getImageData())
                || StringUtil.isEmptyOrNull(ocrRequest.getOcrType())) {
            rglog.error("OCR识别服务失败，必填项参数为空！");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        if (!(ID_CARD_TYPE.equals(ocrRequest.getOcrType())
                || BANK_CARD_TYPE.equals(ocrRequest.getOcrType())
                || LICENSE_TYPE.equals(ocrRequest.getOcrType()))) {
            rglog.error("OCR识别服务失败，识别类型不符合规则！ocrType:{}", ocrRequest.getOcrType());
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }

        return ocrRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        OcrRequest ocrRequest = (OcrRequest) request;
        BizResponse<OcrResponse> bizResponse = new BizResponse<>();
        OcrResponse ocrResponse = new OcrResponse();
        String instId = ocrRequest.getHeader().getInstId();
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
        String imgData = ocrRequest.getImageData();
        String ocrType = ocrRequest.getOcrType();

        if (CollectionUtils.isEmpty(txnInfo.getChannelCallCfgList())
                || txnInfo.getChannelCallCfgList().size() < 3) {
            rglog.error("OCR识别处理失败，txnInfo.getchannelCallCfgList 通道服务调用配置表无ORC身份证识别或银行卡识别配置数据!,instId:{}, sysSeqNum:{}",
                    instId, sysSeqNum);
            throw new BizException(RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespCode(), RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespDesc());
        }

        String json;

        if (ID_CARD_TYPE.equals(ocrType)) {
            Optional<ChannelCallCfg> channelCallCfg = txnInfo.getChannelCallCfgList().stream().filter(item -> "04190000000003".equals(item.getCallChannelTxn())).findFirst();
            if (!channelCallCfg.isPresent()) {
                rglog.error("OCR识别处理失败，txnInfo.getchannelCallCfgList 通道服务调用配置表无ORC身份证识别配置数据!,instId:{}, sysSeqNum:{}",
                        instId, sysSeqNum);
                throw new BizException(RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespCode(), RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespDesc());
            }

            ChannelCallCfg orcIdCardchannelCallCfg = channelCallCfg.get();
            IdentityCertRecogRequest identityCertRecogRequest = new IdentityCertRecogRequest();
            Header queryHeader = new Header();
            queryHeader.setInstId(ocrRequest.getHeader().getInstId());
            queryHeader.setChanlId(ChannelEnum.BOMP.getChannelType());
            queryHeader.setSrcSysId(AppParamConstant.SYS_ID);
            queryHeader.setTxnNum(orcIdCardchannelCallCfg.getCallChannelTxn());
            queryHeader.setTransDate(DateUtil.getCurrentDate());
            queryHeader.setTransTime(DateUtil.getCurrentTime());
            queryHeader.setTraceNo(GlobalEsbUtil.generateEsbSeqeuenceNumber(ocrRequest.getHeader().getInstId()));
            identityCertRecogRequest.setHeader(queryHeader);
            identityCertRecogRequest.setImageInfo(ocrRequest.getImageData());

            DubboService dubboService = new DubboServiceImpl();
            Result<IdentityCertRecogResponse> identityCertRecogResponseResult = (Result<IdentityCertRecogResponse>) dubboService.callDubboService(DubboMethodConstant.DUBBO_OCR_SERVICE, "identityCertRecog", identityCertRecogRequest);
            if (null == identityCertRecogResponseResult) {
                rglog.error("OCR识别处理失败！调用ESB通道的身份证OCR文字识别ocrIdCardInfoRecognResponse返回失败!");
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            } else if (!identityCertRecogResponseResult.isSuccess() || !DubboMethodConstant.DUBBO_SUCCESS.equals(identityCertRecogResponseResult.getResult().getRespCode())) {
                rglog.error("OCR识别处理失败！调用ESB通道的身份证OCR文字识别ocrIdCardInfoRecognResponse返回失败,errorCode:{},errorMsg:{}",
                        identityCertRecogResponseResult.getResult().getRespCode(), identityCertRecogResponseResult.getResult().getRespDesc());
                throw new BizException(identityCertRecogResponseResult.getResult().getRespCode(), identityCertRecogResponseResult.getResult().getRespDesc());
            }
            json = convertOcrIdInfoBean(identityCertRecogResponseResult.getResult());
        } else if (BANK_CARD_TYPE.equals(ocrType)) {
            Optional<ChannelCallCfg> channelCallCfg = txnInfo.getChannelCallCfgList().stream().filter(item -> "04190000000004".equals(item.getCallChannelTxn())).findFirst();
            if (!channelCallCfg.isPresent()) {
                rglog.error("OCR识别处理失败，txnInfo.getchannelCallCfgList 通道服务调用配置表无ORC银行卡识别配置数据!,instId:{}, sysSeqNum:{}",
                        instId, sysSeqNum);
                throw new BizException(RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespCode(), RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespDesc());
            }

            ChannelCallCfg orcBankCardchannelCallCfg = channelCallCfg.get();
            BankCardRecogRequest bankCardRecogRequest = new BankCardRecogRequest();
            Header queryHeader = new Header();
            queryHeader.setInstId(ocrRequest.getHeader().getInstId());
            queryHeader.setChanlId(ChannelEnum.BOMP.getChannelType());
            queryHeader.setSrcSysId(AppParamConstant.SYS_ID);
            queryHeader.setTxnNum(orcBankCardchannelCallCfg.getCallChannelTxn());
            queryHeader.setTransDate(DateUtil.getCurrentDate());
            queryHeader.setTransTime(DateUtil.getCurrentTime());
            queryHeader.setTraceNo(GlobalEsbUtil.generateEsbSeqeuenceNumber(ocrRequest.getHeader().getInstId()));
            bankCardRecogRequest.setHeader(queryHeader);
            bankCardRecogRequest.setImageInfo(ocrRequest.getImageData());
            DubboService dubboService = new DubboServiceImpl();
            Result<BankCardRecogResponse> recognResponseResult = (Result<BankCardRecogResponse>) dubboService.callDubboService(DubboMethodConstant.DUBBO_OCR_SERVICE, "bankCardRecog", bankCardRecogRequest);
            if (null == recognResponseResult) {
                rglog.error("OCR识别处理失败！调用ESB通道的OCR银行卡识别ocrBankCardInfoRecognResponse返回失败!");
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            } else if (!recognResponseResult.isSuccess() || !DubboMethodConstant.DUBBO_SUCCESS.equals(recognResponseResult.getResult().getRespCode())) {
                rglog.error("OCR识别处理失败！调用ESB通道的OCR银行卡识别ocrBankCardInfoRecognResponse返回失败,errorCode:{},errorMsg:{}",
                        recognResponseResult.getResult().getRespCode(), recognResponseResult.getResult().getRespDesc());
                throw new BizException(recognResponseResult.getResult().getRespCode(), recognResponseResult.getResult().getRespDesc());
            }
            json = convertOcrCardInfoBean(recognResponseResult.getResult());
        } else {
            Optional<ChannelCallCfg> channelCallCfg = txnInfo.getChannelCallCfgList().stream().filter(item -> "04190000000001".equals(item.getCallChannelTxn())).findFirst();
            if (!channelCallCfg.isPresent()) {
                rglog.error("OCR识别处理失败，txnInfo.getchannelCallCfgList 通道服务调用配置表无ORC银行卡识别配置数据!,instId:{}, sysSeqNum:{}",
                        instId, sysSeqNum);
                throw new BizException(RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespCode(), RespCodeEnum.CONFIG_PARAM_NOT_EXIST.getRespDesc());
            }

            BusinessLicenseRecogRequest businessLicenseRecogRequest = new BusinessLicenseRecogRequest();
            ChannelCallCfg orcLicensechannelCallCfg = channelCallCfg.get();
            Header queryHeader = new Header();
            queryHeader.setInstId(ocrRequest.getHeader().getInstId());
            queryHeader.setChanlId(ChannelEnum.BOMP.getChannelType());
            queryHeader.setSrcSysId(AppParamConstant.SYS_ID);
            queryHeader.setTxnNum(orcLicensechannelCallCfg.getCallChannelTxn());
            queryHeader.setTransDate(DateUtil.getCurrentDate());
            queryHeader.setTransTime(DateUtil.getCurrentTime());
            queryHeader.setTraceNo(GlobalEsbUtil.generateEsbSeqeuenceNumber(ocrRequest.getHeader().getInstId()));
            businessLicenseRecogRequest.setHeader(queryHeader);
            businessLicenseRecogRequest.setImageInfo(ocrRequest.getImageData());
            DubboService dubboService = new DubboServiceImpl();
            Result<BusinessLicenseRecogResponse> recognResponseResult = (Result<BusinessLicenseRecogResponse>) dubboService.callDubboService(DubboMethodConstant.DUBBO_OCR_SERVICE, "businessLicenseRecog", businessLicenseRecogRequest);
            if (null == recognResponseResult) {
                rglog.error("OCR识别处理失败！调用ESB通道的OCR营业执照识别OcrBusinessLicenseInfoRecognResponse返回失败!");
                throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
            } else if (!recognResponseResult.isSuccess() || !DubboMethodConstant.DUBBO_SUCCESS.equals(recognResponseResult.getResult().getRespCode())) {
                rglog.error("OCR识别处理失败！调用ESB通道的OCR营业执照识别OcrBusinessLicenseInfoRecognResponse返回失败,errorCode:{},errorMsg:{}",
                        recognResponseResult.getResult().getRespCode(), recognResponseResult.getResult().getRespDesc());
                throw new BizException(recognResponseResult.getResult().getRespCode(), recognResponseResult.getResult().getRespDesc());
            }
            json = convertOcrBusinessLicenseInfoBean(recognResponseResult.getResult());
        }

        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        ocrResponse.setOcrResult(json);
        bizResponse.setResult(ocrResponse);
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        OcrResponse ocrResponse = (OcrResponse) bizResponse.getResult();
        ConvertUtil.convertInput(ocrResponse);
    }

    private String convertOcrIdInfoBean(IdentityCertRecogResponse response) throws Exception {
        OcrIdInfoBean ocrIdInfoBean = new OcrIdInfoBean();
        ocrIdInfoBean.setAddress(response.getAddress());
        ocrIdInfoBean.setBirthday(response.getBirthday());
        ocrIdInfoBean.setIdNumber(response.getCertNo());
        ocrIdInfoBean.setIssueAuthority(response.getAuthority());
        ocrIdInfoBean.setName(response.getName());
        ocrIdInfoBean.setPeople(response.getNation());
        ocrIdInfoBean.setSex(response.getSex());
        ocrIdInfoBean.setType(response.getCertType());
        ocrIdInfoBean.setValidity(response.getValidate());
        return JSONObject.toJSONString(ocrIdInfoBean);
    }

    private String convertOcrCardInfoBean(BankCardRecogResponse ocrBankCardInfoRecognResponse) throws Exception {
        OcrCardInfoBean ocrCardInfo = new OcrCardInfoBean();
        ocrCardInfo.setCardNumber(ocrBankCardInfoRecognResponse.getCardNo());
        ocrCardInfo.setIssuer(ocrBankCardInfoRecognResponse.getBankName());
        ocrCardInfo.setType(ocrBankCardInfoRecognResponse.getCardType());
        ocrCardInfo.setValidity(ocrBankCardInfoRecognResponse.getExpireDate());
        return JSONObject.toJSONString(ocrCardInfo);
    }


    private String convertOcrBusinessLicenseInfoBean(BusinessLicenseRecogResponse response) throws Exception {
        OcrBusinessLicenseInfoBean ocrIdInfoBean = new OcrBusinessLicenseInfoBean();
        BeanUtil.beanCopy(response, ocrIdInfoBean);
        return JSONObject.toJSONString(ocrIdInfoBean);
    }
}
